package com.jl.driver.vritual.ternimal;

import javax.comm.*;
import java.io.*;
import java.util.*;

public class COM implements Runnable, SerialPortEventListener,
		CommPortOwnershipListener {
	public final static int DATABITS_5 = SerialPort.DATABITS_5;
	public final static int DATABITS_6 = SerialPort.DATABITS_6;
	public final static int DATABITS_7 = SerialPort.DATABITS_7;
	public final static int DATABITS_8 = SerialPort.DATABITS_8;
	public final static int PARITY_EVEN = SerialPort.PARITY_EVEN;
	public final static int PARITY_MARK = SerialPort.PARITY_MARK;
	public final static int PARITY_NONE = SerialPort.PARITY_NONE;
	public final static int PARITY_ODD = SerialPort.PARITY_ODD;
	public final static int PARITY_SPACE = SerialPort.PARITY_SPACE;
	public final static int STOPBITS_1 = SerialPort.STOPBITS_1;
	public final static int STOPBITS_1_5 = SerialPort.STOPBITS_1_5;
	public final static int STOPBITS_2 = SerialPort.STOPBITS_2;

	public final static int TIMEOUT_DEFAULT = 1000 * 5;

	private CommPortIdentifier _PORT = null;
	private SerialPort _S = null;
	private MBUF _M = null;

	private InputStream _I;
	private OutputStream _O;

	static {
		System.loadLibrary("win32com");
	}

	public static String[] listPorts() {
		Vector<Object> v = new Vector<Object>();
		Enumeration<?> e = CommPortIdentifier.getPortIdentifiers();
		while (e.hasMoreElements())
			v.addElement(e.nextElement());
		String[] ss = new String[v.size()];
		for (int i = 0; i < ss.length; i++) {
			ss[i] = ((CommPortIdentifier) (v.elementAt(i))).getName();

			// System.out.println("Port " + i + ": " + ss[i]);
		}
		return ss;
	}

	@Override
	public void ownershipChange(int type) {

	}

	public COM(String name) throws COMException {
		try {
			_PORT = CommPortIdentifier.getPortIdentifier(name);
		} catch (Exception ex) {
			COMException.throwIt(ex);
		}

	}

	public int open(int baudrate, int dataBits, int stopBits, int parity,
			boolean DTR, boolean RTS) throws COMException {
		try {
			_S = (SerialPort) _PORT.open("ComControl", 2000);
			_S.setSerialPortParams(baudrate, dataBits, stopBits, parity);
			_S.setDTR(DTR);
			_S.setRTS(RTS);
			_I = _S.getInputStream();
			_O = _S.getOutputStream();
			_M = new MBUF();
			_S.addEventListener(this);
			_S.notifyOnDataAvailable(true);
			(new Thread(this)).start();
		} catch (Exception ex) {
			COMException.throwIt(ex);
		}
		return 0;
	}

	@Override
	public void run() {
	}

	@Override
	public void serialEvent(SerialPortEvent event) {
		switch (event.getEventType()) {
		case SerialPortEvent.BI:
		case SerialPortEvent.OE:
		case SerialPortEvent.FE:
		case SerialPortEvent.PE:
		case SerialPortEvent.CD:
		case SerialPortEvent.CTS:
		case SerialPortEvent.DSR:
		case SerialPortEvent.RI:
			break;
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			break;
		case SerialPortEvent.DATA_AVAILABLE:
			_M.fill(_I);
			break;
		}
	}

	public int read(int timeout, byte[] buf, int offset) {
		int length = 0;
		int len = 0;
		long t0 = (System.currentTimeMillis() + timeout);

		while ((t0 - System.currentTimeMillis()) > 0) {
			len = _M.read(buf, offset, buf.length - offset);
			if (len < 0)
				return -1;
			offset += len;
			length += len;
		}
		return length;
	}

	public int read(byte[] buf, int offset) {
		return read(TIMEOUT_DEFAULT, buf, offset);
	}

	public int read(int timeout, byte[] buf, int offset, int length) {
		int len = 0;
		long t0 = (System.currentTimeMillis() + timeout);

		while (length > 0 && (t0 - System.currentTimeMillis()) > 0) {
			// System.out.println("Need " + length + " bytes..");
			len = _M.read(buf, offset, length);
			if (len < 0)
				return -1;
			offset += len;
			length -= len;
		}
		if (length > 0)
			return -2;
		return 0;
	}

	public int read(byte[] buf, int offset, int length) {
		return read(TIMEOUT_DEFAULT, buf, offset, length);
	}

	public int write(byte[] buf, int offset, int length) {
		try {
			_O.write(buf, offset, length);
		} catch (Exception ex) {
			return -1;
		}
		return 0;
	}

	public int available() {
		return _M.available();
	}

	public void close() {
		if (_S != null)
			_S.removeEventListener();
		try {
			_I.close();
			_O.close();
		} catch (Exception ex) {
		}
		_M = null;
		if (_S != null)
			_S.close();
	}

	public void setS1(boolean s1) {
		_S.setDTR(s1);
	}

	public void setS2(boolean s2) {
		_S.setRTS(s2);
	}

	public int test(byte[] buf) {
		try {
			return read(buf, 0);

		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return -1;
	}

}